<template>
    <div class="trigger-condition-wrapper" ref="triggerConditionRef">
        <el-form-item
            label="触发条件"
            prop="condition"
            label-position="top"
            class="trigger-condition-form-item"
            :rules="rules"
        >
            <el-table :data="tableData" border>
                <el-table-column type="index" label="序号" width="60" align="center" />
                <el-table-column label="触发条件（多条是 或 ）" align="center" cell>
                    <template #default="scope">
                        <div class="condition-box">
                            <el-select
                                :class="{ error: !scope.row.scriptName }"
                                v-if="conditionType == 'SCRIPT_CONDITION'"
                                placeholder="请选择脚本"
                                v-model="scope.row.scriptName"
                                filterable
                            >
                                <el-option
                                    v-for="(item, i) in scriptList"
                                    :label="item.scriptName"
                                    :key="i"
                                    :value="item.scriptNo"
                                />
                            </el-select>
                            <el-select
                                :class="{ error: !scope.row.spiName }"
                                v-else-if="conditionType == 'SPI_CONDITION'"
                                placeholder="请选SPI"
                                v-model="scope.row.spiName"
                                filterable
                            >
                                <el-option
                                    v-for="(item, i) in spiList"
                                    :label="item.handlerName"
                                    :key="i"
                                    :value="item.handlerName"
                                />
                            </el-select>
                            <template v-else>
                                <div style="margin-right: 10px">
                                    <ModelAttributeChoice
                                        @change="val => onModelAttributeChange(val, scope.row)"
                                        :modelDetail="modelDetail"
                                        :defaultData="toModelAttributeData(scope.row)"
                                        :attrRestrict="conditionType"
                                    />
                                </div>
                                <template v-if="conditionType == 'BASIC_CONDITION'">
                                    <el-select
                                        :class="{ error: !scope.row.additional.operator }"
                                        placeholder="运算符"
                                        v-model="scope.row.additional.operator"
                                        style="width: 80px; flex: 0 0 auto"
                                    >
                                        <el-option
                                            v-for="(value, key) in filterOperator(scope.row)"
                                            :label="value"
                                            :key="key"
                                            :value="key"
                                        />
                                    </el-select>
                                    <el-select
                                        :class="{ error: !scope.row.additional.valueType }"
                                        v-model="scope.row.additional.valueType"
                                        placeholder="值类型"
                                        style="width: 100px; flex: 0 0 auto"
                                        @change="
                                            () => {
                                                scope.row.additional.data = '';
                                            }
                                        "
                                    >
                                        <el-option
                                            v-for="(value, key) in ValueType"
                                            :label="value"
                                            :key="key"
                                            :value="key"
                                        />
                                    </el-select>
                                    <template v-if="scope.row.additional.valueType == 'Func'">
                                        <el-button
                                            type="primary"
                                            link
                                            style="width: 177.33px; flex: 0 0 auto; margin-left: 5px"
                                            @click="onExpression(scope.row)"
                                        >
                                            定义函数表达式
                                        </el-button>
                                    </template>
                                    <template v-else-if="scope.row.additional.valueType == 'Attribute'">
                                        <el-select
                                            :disabled="!scope.row.attribute.attributeName"
                                            :class="{ error: !scope.row.additional.data }"
                                            placeholder="请选择模型属性"
                                            v-model="scope.row.additional.data"
                                            filterable
                                        >
                                            <el-option
                                                v-for="item in filterAttribute(scope.row)"
                                                :key="item.id"
                                                :label="item.displayName"
                                                :value="item.attributeName"
                                            />
                                        </el-select>
                                    </template>
                                    <template v-else>
                                        <el-input
                                            :class="{ error: !scope.row.additional.data }"
                                            placeholder="请输入"
                                            v-model="scope.row.additional.data"
                                            maxlength="50"
                                        />
                                    </template>
                                </template>
                                <template v-else-if="conditionType == 'LENGTH_CONDITION'">
                                    <el-input-number
                                        :class="{ error: !scope.row.length }"
                                        placeholder="请输入"
                                        v-model="scope.row.length"
                                        :min="0"
                                        :step="1"
                                        :precision="0"
                                        controls-position="right"
                                        maxlength="50"
                                    />
                                </template>
                            </template>
                        </div>
                    </template>
                </el-table-column>
                <el-table-column width="60" align="center">
                    <template #header>
                        <el-button :icon="Plus" type="primary" @click="add" size="small"></el-button>
                    </template>
                    <template #default="scope">
                        <el-button :icon="Minus" type="danger" @click="del(scope.$index)" size="small"></el-button>
                    </template>
                </el-table-column>
            </el-table>
        </el-form-item>
    </div>
</template>
<script setup lang="ts">
import { Plus, Minus } from '@element-plus/icons-vue';
import { showPopupBox } from '@great/utils';
import { formContextKey } from 'element-plus';
import ExpressionModal from './ExpressionModal.vue';
import ModelAttributeChoice from './ModelAttributeChoice.vue';
import { useRequest } from 'vue-request';
import { modelService, runScriptService, runSpiService } from '@great/services';

const props = defineProps<{
    row?: Record<string, any>;
    conditionType: string;
    modelDetail: Record<string, any>;
}>();

// 运算符枚举
enum Operator {
    EQ = '=',
    LT = '<',
    GT = '>',
    GE = '>=',
    LE = '<=',
    NE = '<>',
    IN = '包含',
    NOTIN = '不包含'
}

enum ValueType {
    Constant = '字符常量',
    Attribute = '属性值',
    Func = '函数表达式'
}

interface TableData {
    type: string;
    model?: string; // 模型
    // 属性
    attribute?: {
        displayName: string;
        attributeName: string;
        expression: string;
        typeName: string;
    };
    additional?: {
        operator: string; // 运算符
        valueType: string; // 值类型（常量值、属性值、函数表达式）
        data: string; // 值、属性值、函数表达式
    };
    length?: number | null; // 长度
    scriptName?: string; // 脚本
    spiName?: string; //spi
}

const elementRef = useTemplateRef('triggerConditionRef');
const tableData = ref<Array<TableData>>([]);
const attributeListMap = ref<Record<string, any>>({});
const scriptList = ref<any>([]);
const spiList = ref<any>([]);
const formInstance = inject(formContextKey);
const rules = reactive([
    {
        validator: (rule: any, value: any, callback: any) => {
            if (elementRef.value?.querySelector('.error')) {
                return callback(new Error('请完善参数配置'));
            }
            return callback();
        },
        trigger: ['blur', 'change']
    }
]);
const add = () => {
    if (props.conditionType) {
        if (elementRef.value?.querySelector('.error')) {
            ElNotification({
                message: '请完成当前配置',
                type: 'warning'
            });
        } else {
            if (props.conditionType == 'BASIC_CONDITION') {
                tableData.value.push({
                    type: props.conditionType,
                    model: '',
                    attribute: {
                        displayName: '',
                        attributeName: '',
                        expression: '',
                        typeName: ''
                    },
                    additional: {
                        operator: '',
                        valueType: 'Constant',
                        data: ''
                    }
                });
            } else if (props.conditionType == 'LENGTH_CONDITION') {
                tableData.value.push({
                    type: props.conditionType,
                    model: '',
                    attribute: {
                        displayName: '',
                        attributeName: '',
                        expression: '',
                        typeName: ''
                    },
                    length: null
                });
            } else if (props.conditionType == 'SCRIPT_CONDITION') {
                tableData.value.push({ type: props.conditionType, scriptName: '' });
                getScriptList();
            } else if (props.conditionType == 'SPI_CONDITION') {
                tableData.value.push({ type: props.conditionType, spiName: '' });
                getSpiList();
            } else if (props.conditionType == 'UNIQUE_CONDITION') {
                tableData.value.push({
                    type: props.conditionType,
                    model: '',
                    attribute: {
                        displayName: '',
                        attributeName: '',
                        expression: '',
                        typeName: ''
                    }
                });
            }
        }
    } else {
        ElNotification({
            message: '触发条件类型不能为空！',
            type: 'warning'
        });
    }
};

const del = (index: number) => {
    tableData.value.splice(index, 1);
    if (tableData.value.length == 0) {
        formInstance?.clearValidate('condition');
    }
};
// 运算符过滤
const filterOperator = (row: any) => {
    if (row.type == 'BASIC_CONDITION') {
        if (row.attribute && row.attribute.attributeName && row.attribute.typeName) {
            const persistType = attributeTypeList.value[row.attribute.typeName].persistType;
            if (persistType == 'String') {
                // string类型  = <> 包含 不包含
                enum TargetData {
                    EQ = '=',
                    NE = '<>',
                    IN = '包含',
                    NOTIN = '不包含'
                }
                return TargetData;
            } else if (persistType == 'Number' || persistType == 'Date') {
                // number,date类型 = <> > < >= <=
                enum TargetData {
                    EQ = '=',
                    LT = '<',
                    GT = '>',
                    GE = '>=',
                    LE = '<=',
                    NE = '<>'
                }
                return TargetData;
            }
        }
        // bool或其它类型  = <>
        enum TargetData {
            EQ = '=',
            NE = '<>'
        }
        return TargetData;
    } else {
        return Operator;
    }
};
// 属性值-属性过滤
const filterAttribute = (row: any): Array<any> => {
    if (row && row.model && row.attribute) {
        const excludeTypeName = ['Rich-Text', 'JSON', 'Lookup', 'Cascade-Lookup', 'Expression']; // 固定排除的类型
        let targetData = JSON.parse(JSON.stringify(attributeListMap.value[row.model] || []));
        targetData = targetData.filter(item => {
            if (!excludeTypeName.includes(item.typeName)) return item;
        });
        const persistType = attributeTypeList.value[row.attribute.typeName].persistType; // 依据所选属性类型进行过滤
        const filteredKeys = Object.entries(attributeTypeList.value)
            .filter(([key, value]: any) => value.persistType === persistType)
            .map(([key, value]) => key);
        targetData = targetData.filter(item => filteredKeys.includes(item.typeName)); // 只保留和所选属性类型一致的属性
        return targetData;
    } else {
        return [];
    }
};
// 函数表达式
const onExpression = (row: any) => {
    showPopupBox(ExpressionModal, {
        expression: row.additional.data,
        callBack: (par?: string): void => {
            row.additional.data = par;
        }
    });
};
// 属性切换
const onAttributeChange = (attributeData, row?: any) => {
    let targetData = attributeData.find(item => item.attributeName === row.attribute.attributeName);
    row.attribute.displayName = targetData.displayName;
    row.attribute.expression = `${row.model}.${targetData.attributeName}`;
    row.attribute.typeName = targetData.typeName;
    if (row.type == 'BASIC_CONDITION') {
        // 清空运算符
        row.additional.operator = '';
        if (row.additional.valueType === 'Attribute') {
            // 如果是属性值，清空所选属性
            row.additional.data = '';
        }
    }
};
const onModelAttributeChange = (modelAttribute, row) => {
    if (modelAttribute.changeType == 'model') {
        row.model = modelAttribute.modelData.objectName;
        attributeListMap.value[modelAttribute.modelData.objectName] = modelAttribute.attributeData;
    } else {
        row.attribute.attributeName = modelAttribute.attribute;
        onAttributeChange(modelAttribute.attributeData, row);
    }
};
// 获取脚本列表
const getScriptList = async () => {
    if (scriptList.value && scriptList.value.length) return;
    const res = await runScriptService.getScriptList({
        scriptType: 'scriptCondition'
    });
    scriptList.value = res.data;
};
// 获取SPI列表
const getSpiList = async () => {
    if (spiList.value && spiList.value.length) return;
    const res = await runSpiService.getSpiList('OBJECT_RULE');
    spiList.value = res.data;
};

const getCondition = (): Array<TableData> => {
    if (props.conditionType == 'SCRIPT_CONDITION') {
        return JSON.parse(JSON.stringify(tableData.value));
    } else {
        return JSON.parse(JSON.stringify(tableData.value)).map(item => {
            delete item.model;
            return item;
        });
    }
};
const escapeRegExp = (str: string) => {
    return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
};
const toModelAttributeData = (row: any): { model: string; attribute: string } => {
    let targetData: { model: string; attribute: string } = { model: row.model, attribute: row.attribute.attributeName };
    return targetData;
};
const dataInit = () => {
    if (props.row) {
        let sourceData = JSON.parse(props.row.basicCondition);
        if (sourceData.length && sourceData[0].type == props.conditionType) {
            tableData.value = sourceData.map((item, i) => {
                if (item.attribute) {
                    const regex = new RegExp(`\\.${escapeRegExp(item.attribute.attributeName)}$`);
                    item.model = item.attribute.expression.replace(regex, '');
                } else if (item.type === 'SCRIPT_CONDITION') {
                    getScriptList();
                } else if (item.type === 'SPI_CONDITION') {
                    getSpiList();
                }
                return item;
            });
        } else {
            tableData.value = [];
        }
    } else {
        tableData.value = [];
    }
};

const { data: typeData } = useRequest(modelService.attribute.getTypeList, {
    cacheKey: 'attributeTypeList',
    staleTime: -1
});
const attributeTypeList = computed(() => {
    return typeData.value?.data || {};
});

defineExpose({
    getCondition
});

// 监听
watch(
    () => props.conditionType,
    () => {
        dataInit();
    },
    {
        immediate: true
    }
);
</script>
<style scoped lang="scss">
.trigger-condition-wrapper {
    width: 100%;
    :deep(.trigger-condition-form-item.is-error) {
        .el-form-item__content {
            border: none;
            border-radius: 0;
            padding: 0;
        }
        .el-select__wrapper,
        .el-input__wrapper {
            box-shadow: 0 0 0 1px var(--el-border-color) inset !important;
        }

        .el-input.error {
            .el-input__wrapper {
                box-shadow: 0 0 0 1px var(--el-color-danger) inset !important;
            }
        }
        .el-select.error {
            .el-select__wrapper {
                box-shadow: 0 0 0 1px var(--el-color-danger) inset !important;
            }
        }
    }
    :deep(.el-table) {
        .condition-box {
            display: flex;
            > div {
                flex: 1;
            }
            > div + div {
                margin-left: 5px;
            }
        }
    }
}
</style>
